﻿
Imports osi.root.constants
Imports osi.root.connector
Imports osi.root.formation
Imports osi.root.utils
Imports osi.root.procedure
Imports osi.service.argument
Imports osi.service.convertor
Imports osi.service.device
Imports osi.service.selector

<global_init(global_init_level.server_services)>
Public Class target_questioner
    Private ReadOnly name() As Byte
    Private ReadOnly q As questioner

    Shared Sub New()
        bind_default_bytes_conversion()
    End Sub

    Private Sub New(ByVal name() As Byte,
                    ByVal q As questioner,
                    ByVal interval As Boolean)
        assert(Not isemptyarray(name))
        assert(Not q Is Nothing)
        Me.name = name
        Me.q = q
    End Sub

    Public Sub New(ByVal name() As Byte,
                   ByVal q As questioner)
        Me.New(copy(name), q, True)
    End Sub

    Public Shared Function ctor(Of KEY_T)(ByVal name As KEY_T,
                                          ByVal q As questioner,
                                          Optional ByVal key_t_bytes As  _
                                              binder(Of Func(Of KEY_T, Byte()), 
                                                        bytes_conversion_binder_protector) = Nothing) As target_questioner
        assert(key_t_bytes.has_value())
        Return New target_questioner((+key_t_bytes)(name), q, True)
    End Function

    Public Function [get]() As questioner
        Return q
    End Function

    Public Shared Operator +(ByVal i As target_questioner) As questioner
        If i Is Nothing Then
            Return Nothing
        Else
            Return i.get()
        End If
    End Operator

    Private Function append_parameter_name(ByVal request As command) As Boolean
        If request Is Nothing OrElse
           request.has_parameter(constants.parameter.name) Then
            Return False
        Else
            request.attach(constants.parameter.name, name)
            Return True
        End If
    End Function

    Default Public ReadOnly Property question(ByVal request As command,
                                              ByVal response As pointer(Of command)) As event_comb
        Get
            Dim ec As event_comb = Nothing
            Return New event_comb(Function() As Boolean
                                      If append_parameter_name(request) Then
                                          ec = q(request, response)
                                          Return waitfor(ec) AndAlso
                                                 goto_next()
                                      Else
                                          Return False
                                      End If
                                  End Function,
                                  Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             goto_end()
                                  End Function)
        End Get
    End Property

    Default Public ReadOnly Property question(ByVal request As command,
                                              ByVal response As Func(Of command, Boolean)) As event_comb
        Get
            Dim ec As event_comb = Nothing
            Return New event_comb(Function() As Boolean
                                      If append_parameter_name(request) Then
                                          ec = q(request, response)
                                          Return waitfor(ec) AndAlso
                                                 goto_next()
                                      Else
                                          Return False
                                      End If
                                  End Function,
                                  Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             goto_end()
                                  End Function)
        End Get
    End Property

    Default Public ReadOnly Property question(ByVal request As command,
                                              ByVal response As Func(Of Boolean)) As event_comb
        Get
            Dim ec As event_comb = Nothing
            Return New event_comb(Function() As Boolean
                                      If append_parameter_name(request) Then
                                          ec = q(request, response)
                                          Return waitfor(ec) AndAlso
                                                 goto_next()
                                      Else
                                          Return False
                                      End If
                                  End Function,
                                  Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             goto_end()
                                  End Function)
        End Get
    End Property

    Default Public ReadOnly Property question(ByVal request As command) As event_comb
        Get
            Dim ec As event_comb = Nothing
            Return New event_comb(Function() As Boolean
                                      If append_parameter_name(request) Then
                                          ec = q(request)
                                          Return waitfor(ec) AndAlso
                                                 goto_next()
                                      Else
                                          Return False
                                      End If
                                  End Function,
                                  Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             goto_end()
                                  End Function)
        End Get
    End Property

    Private Shared Function create(ByVal v As var,
                                   ByVal q As questioner,
                                   ByRef o As target_questioner) As Boolean
        If v Is Nothing OrElse q Is Nothing Then
            Return False
        Else
            Dim target As String = Nothing
            If v.value("target", target) Then
                o = ctor(target, q)
                Return True
            Else
                Return False
            End If
        End If
    End Function

    Private Shared Function create(ByVal v As var,
                                   ByVal q As questioner,
                                   ByVal o As pointer(Of target_questioner)) As event_comb
        Return sync_async(Function() As Boolean
                              Dim r As target_questioner = Nothing
                              Return create(v, q, r) AndAlso
                                     eva(o, r)
                          End Function)
    End Function

    Public Shared Function create(ByVal v As var, ByVal o As pointer(Of target_questioner)) As event_comb
        Return secondary_resolve(v,
                                 Function(i As questioner, ByRef r As target_questioner) As Boolean
                                     Return create(v, i, r)
                                 End Function,
                                 o)
    End Function

    Private Shared Sub init()
        device_constructor.set_create_singleton_device_pool_binder(
            Function(x As target_questioner) As singleton_device_pool(Of target_questioner)
                Return New singleton_device_pool(Of target_questioner)(x)
            End Function)
        assert(device_constructor.register(Of target_questioner) _
                                          (Function(v As var, o As pointer(Of target_questioner)) As event_comb
                                               Return create(v, o)
                                           End Function))
#If 0 Then
        assert(device_constructor.register(
                   dependent_allocator("questioner",
                                       Function(q As questioner,
                                                v As var,
                                                o As pointer(Of target_questioner)) As event_comb
                                           Return create(v, q, o)
                                       End Function)))
#End If
        assert(device_constructor.register(parameter_allocator(Function(v As var,
                                                                        q As questioner,
                                                                        ByRef o As target_questioner) As Boolean
                                                                   Return create(v, q, o)
                                                               End Function)))
    End Sub
End Class
